home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / BumpMapping / Emboss / Emboss.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  20.8 KB  |  586 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Emboss.cpp
  3. //
  4. // Desc: Shows how to do a bumpmapping technique called emobssing, in which a
  5. //       heightmap is subtracted from itself, with slightly offset texture
  6. //       coordinates for the second pass.
  7. //
  8. // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  9. //-----------------------------------------------------------------------------
  10. #define STRICT
  11. #include <math.h>
  12. #include <stdio.h>
  13. #include <D3DX8.h>
  14. #include "D3DApp.h"
  15. #include "D3DFont.h"
  16. #include "D3DFile.h"
  17. #include "D3DUtil.h"
  18. #include "DXUtil.h"
  19. #include "resource.h"
  20.  
  21.  
  22.  
  23.  
  24. //-----------------------------------------------------------------------------
  25. // Defines, constants, and global variables
  26. //-----------------------------------------------------------------------------
  27. struct EMBOSSVERTEX 
  28. {
  29.     D3DXVECTOR3 p;
  30.     D3DXVECTOR3 n;
  31.     FLOAT       tu,  tv;
  32.     FLOAT       tu2, tv2;
  33. };
  34.  
  35. #define D3DFVF_EMBOSSVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2)
  36.  
  37.  
  38.  
  39.  
  40. //-----------------------------------------------------------------------------
  41. // Name: class CMyD3DApplication
  42. // Desc: Application class. The base class (CD3DApplication) provides the 
  43. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  44. //       adds functionality specific to this sample program.
  45. //-----------------------------------------------------------------------------
  46. class CMyD3DApplication : public CD3DApplication
  47. {
  48.     CD3DFont*    m_pFont;                    // Font for drawing text
  49.     CD3DMesh*    m_pObject;                  // Object to render
  50.     D3DLIGHT8    m_Light;                    // The light
  51.     BOOL         m_bShowEmbossMethod;        // Whether to do the embossing
  52.  
  53.     LPDIRECT3DTEXTURE8 m_pEmbossTexture;     // The emboss texture
  54.     D3DXVECTOR3  m_vBumpLightPos;            // Light position
  55.     D3DXVECTOR3* m_pTangents;                // Array of vertex tangents
  56.     D3DXVECTOR3* m_pBinormals;               // Array of vertex binormals
  57.  
  58.     // Internal functions
  59.     HRESULT ConfirmDevice( D3DCAPS8*, DWORD, D3DFORMAT );
  60.     LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  61.     VOID    ApplyEnvironmentMap();
  62.     VOID    ComputeTangentsAndBinormals();
  63.  
  64. protected:
  65.     HRESULT OneTimeSceneInit();
  66.     HRESULT InitDeviceObjects();
  67.     HRESULT RestoreDeviceObjects();
  68.     HRESULT InvalidateDeviceObjects();
  69.     HRESULT DeleteDeviceObjects();
  70.     HRESULT Render();
  71.     HRESULT FrameMove();
  72.     HRESULT FinalCleanup();
  73.  
  74. public:
  75.     CMyD3DApplication();
  76. };
  77.  
  78.  
  79.  
  80.  
  81. //-----------------------------------------------------------------------------
  82. // Name: WinMain()
  83. // Desc: Entry point to the program. Initializes everything, and goes into a
  84. //       message-processing loop. Idle time is used to render the scene.
  85. //-----------------------------------------------------------------------------
  86. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  87. {
  88.     CMyD3DApplication d3dApp;
  89.  
  90.     if( FAILED( d3dApp.Create( hInst ) ) )
  91.         return 0;
  92.  
  93.     return d3dApp.Run();
  94. }
  95.  
  96.  
  97.  
  98.  
  99. //-----------------------------------------------------------------------------
  100. // Name: CMyD3DApplication()
  101. // Desc: Application constructor. Sets attributes for the app.
  102. //-----------------------------------------------------------------------------
  103. CMyD3DApplication::CMyD3DApplication()
  104. {
  105.     m_strWindowTitle    = _T("Emboss: BumpMapping Technique");
  106.     m_bUseDepthBuffer   = TRUE;
  107.     m_bShowCursorWhenFullscreen = TRUE;
  108.  
  109.     m_pFont             = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  110.     m_pObject           = new CD3DMesh();
  111.     m_pEmbossTexture    = NULL;
  112.     m_bShowEmbossMethod = TRUE;
  113.     m_pTangents         = NULL;
  114.     m_pBinormals        = NULL;
  115. }
  116.  
  117.  
  118.  
  119.  
  120. //-----------------------------------------------------------------------------
  121. // Name: OneTimeSceneInit()
  122. // Desc: Called during initial app startup, this function performs all the
  123. //       permanent initialization.
  124. //-----------------------------------------------------------------------------
  125. HRESULT CMyD3DApplication::OneTimeSceneInit()
  126. {
  127.     return S_OK;
  128. }
  129.  
  130.  
  131.  
  132.  
  133. //-----------------------------------------------------------------------------
  134. // Name: ComputeTangentVector()
  135. // Desc: To find a tangent that heads in the direction of +tv(texcoords), find
  136. //       the components of both vectors on the tangent surface, and add a 
  137. //       linear combination of the two projections that head in the +tv direction
  138. //-----------------------------------------------------------------------------
  139. D3DXVECTOR3 ComputeTangentVector( EMBOSSVERTEX pVtxA, EMBOSSVERTEX pVtxB, 
  140.                                   EMBOSSVERTEX pVtxC )
  141. {
  142.     D3DXVECTOR3 vAB = pVtxB.p - pVtxA.p;
  143.     D3DXVECTOR3 vAC = pVtxC.p - pVtxA.p;
  144.     D3DXVECTOR3 n   = pVtxA.n;
  145.  
  146.     // Components of vectors to neghboring vertices that are orthogonal to the
  147.     // vertex normal
  148.     D3DXVECTOR3 vProjAB = vAB - ( D3DXVec3Dot( &n, &vAB ) * n );
  149.     D3DXVECTOR3 vProjAC = vAC - ( D3DXVec3Dot( &n, &vAC ) * n );
  150.  
  151.     // tu and tv texture coordinate differences
  152.     FLOAT duAB = pVtxB.tu - pVtxA.tu;
  153.     FLOAT duAC = pVtxC.tu - pVtxA.tu;
  154.     FLOAT dvAB = pVtxB.tv - pVtxA.tv;
  155.     FLOAT dvAC = pVtxC.tv - pVtxA.tv;
  156.  
  157.     if( duAC*dvAB > duAB*dvAC )
  158.     {
  159.         duAC = -duAC;
  160.         duAB = -duAB;
  161.     }
  162.     
  163.     D3DXVECTOR3 vTangent = duAC*vProjAB - duAB*vProjAC;
  164.     D3DXVec3Normalize( &vTangent, &vTangent );
  165.     return vTangent;
  166. }
  167.  
  168.  
  169.  
  170.  
  171. //-----------------------------------------------------------------------------
  172. // Name: 
  173. // Desc: 
  174. //-----------------------------------------------------------------------------
  175. VOID CMyD3DApplication::ComputeTangentsAndBinormals()
  176. {
  177.     EMBOSSVERTEX* pVertices;
  178.     WORD*         pIndices;
  179.     DWORD         dwNumVertices;
  180.     DWORD         dwNumIndices;
  181.  
  182.     // Gain access to the object's vertex and index buffers
  183.     LPDIRECT3DVERTEXBUFFER8 pVB;
  184.     m_pObject->GetSysMemMesh()->GetVertexBuffer( &pVB );
  185.     pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 );
  186.     dwNumVertices = m_pObject->GetSysMemMesh()->GetNumVertices();
  187.  
  188.     LPDIRECT3DINDEXBUFFER8 pIB;
  189.     m_pObject->GetSysMemMesh()->GetIndexBuffer( &pIB );
  190.     pIB->Lock( 0, 0, (BYTE**)&pIndices, 0 );
  191.     dwNumIndices  = m_pObject->GetSysMemMesh()->GetNumFaces() * 3;
  192.  
  193.     // Allocate space for the vertices' tangents and binormals
  194.     m_pTangents  = new D3DXVECTOR3[dwNumVertices];
  195.     m_pBinormals = new D3DXVECTOR3[dwNumVertices];
  196.     ZeroMemory( m_pTangents,  sizeof(D3DXVECTOR3)*dwNumVertices );
  197.     ZeroMemory( m_pBinormals, sizeof(D3DXVECTOR3)*dwNumVertices );
  198.  
  199.     // Generate the vertices' tangents and binormals
  200.     for( DWORD i=0; i<dwNumIndices; i+=3 )
  201.     {
  202.         WORD a = pIndices[i+0];
  203.         WORD b = pIndices[i+1];
  204.         WORD c = pIndices[i+2];
  205.  
  206.         // To find a tangent that heads in the direction of +tv(texcoords),
  207.         // find the components of both vectors on the tangent surface ,
  208.         // and add a linear combination of the two projections that head in the +tv direction
  209.         m_pTangents[a] += ComputeTangentVector( pVertices[a], pVertices[b], pVertices[c] );
  210.         m_pTangents[b] += ComputeTangentVector( pVertices[b], pVertices[a], pVertices[c] );
  211.         m_pTangents[c] += ComputeTangentVector( pVertices[c], pVertices[a], pVertices[b] );
  212.     }
  213.  
  214.     for( i=0; i<dwNumVertices; i++ )
  215.     {
  216.         // Normalize the tangents
  217.         D3DXVec3Normalize( &m_pTangents[i], &m_pTangents[i] );
  218.  
  219.         // Compute the binormals
  220.         D3DXVec3Cross( &m_pBinormals[i], &pVertices[i].n, &m_pTangents[i] );
  221.     }
  222.  
  223.     // Unlock and release the vertex and index buffers
  224.     pIB->Unlock();
  225.     pVB->Unlock();
  226.     pIB->Release();
  227.     pVB->Release();
  228. }
  229.  
  230.  
  231.  
  232.  
  233. //-----------------------------------------------------------------------------
  234. // Name: ApplyEnvironmentMap()
  235. // Desc: Performs a calculation on each of the vertices' normals to determine
  236. //       what the texture coordinates should be for the environment map (in this 
  237. //       case the bump map).
  238. //-----------------------------------------------------------------------------
  239. VOID CMyD3DApplication::ApplyEnvironmentMap()
  240. {
  241.     EMBOSSVERTEX* pv;
  242.     DWORD         dwNumVertices;
  243.     dwNumVertices = m_pObject->GetLocalMesh()->GetNumVertices();
  244.  
  245.     LPDIRECT3DVERTEXBUFFER8 pVB;
  246.     m_pObject->GetLocalMesh()->GetVertexBuffer( &pVB );
  247.     pVB->Lock( 0, 0, (BYTE**)&pv, 0 );
  248.  
  249.     // Get the World matrix
  250.     D3DXMATRIX  WV,InvWV;
  251.     m_pd3dDevice->GetTransform( D3DTS_WORLD, &WV );
  252.     D3DXMatrixInverse( &InvWV, NULL, &WV );
  253.     
  254.     // Get the current light position in object space
  255.     D3DXVECTOR4 vTransformed;
  256.     D3DXVec3Transform( &vTransformed, (D3DXVECTOR3*)&m_Light.Position, &InvWV );
  257.     m_vBumpLightPos.x = vTransformed.x;
  258.     m_vBumpLightPos.y = vTransformed.y;
  259.     m_vBumpLightPos.z = vTransformed.z;
  260.  
  261.     // Dimensions of texture needed for shifting tex coords
  262.     D3DSURFACE_DESC d3dsd;
  263.     m_pEmbossTexture->GetLevelDesc( 0, &d3dsd );
  264.     
  265.     // Loop through the vertices, transforming each one and calculating
  266.     // the correct texture coordinates.
  267.     for( WORD i = 0; i < dwNumVertices; i++ )
  268.     {
  269.         // Find light vector in tangent space
  270.         D3DXVECTOR3 vLightToVertex;
  271.         D3DXVec3Normalize( &vLightToVertex, &(m_vBumpLightPos - pv[i].p) );
  272.         
  273.         // Create rotation matrix (rotate into tangent space)
  274.         FLOAT r = D3DXVec3Dot( &vLightToVertex, &pv[i].n );
  275.  
  276.         if( r < 0.f ) 
  277.         {
  278.             // Don't shift coordinates when light below surface
  279.             pv[i].tu2 = pv[i].tu;
  280.             pv[i].tv2 = pv[i].tv;
  281.         }
  282.         else
  283.         {
  284.             // Shift coordinates for the emboss effect
  285.             D3DXVECTOR2 vEmbossShift;
  286.             vEmbossShift.x = D3DXVec3Dot( &vLightToVertex, &m_pTangents[i] );
  287.             vEmbossShift.y = D3DXVec3Dot( &vLightToVertex, &m_pBinormals[i] );
  288.             D3DXVec2Normalize( &vEmbossShift, &vEmbossShift );
  289.             pv[i].tu2 = pv[i].tu + vEmbossShift.x/d3dsd.Width;
  290.             pv[i].tv2 = pv[i].tv - vEmbossShift.y/d3dsd.Height;
  291.         }
  292.     }
  293.  
  294.     pVB->Unlock();
  295.     pVB->Release();
  296. }
  297.  
  298.  
  299.  
  300.  
  301. //-----------------------------------------------------------------------------
  302. // Name: FrameMove()
  303. // Desc: Called once per frame, the call is the entry point for animating
  304. //       the scene.
  305. //-----------------------------------------------------------------------------
  306. HRESULT CMyD3DApplication::FrameMove()
  307. {
  308.     // Rotate the object
  309.     D3DXMATRIX matWorld;
  310.     D3DXMatrixRotationY( &matWorld, m_fTime );
  311.     m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  312.  
  313.     return S_OK;
  314. }
  315.  
  316.  
  317.  
  318.  
  319. //-----------------------------------------------------------------------------
  320. // Name: Render()
  321. // Desc: Called once per frame, the call is the entry point for 3d
  322. //       rendering. This function sets up render states, clears the
  323. //       viewport, and renders the scene.
  324. //-----------------------------------------------------------------------------
  325. HRESULT CMyD3DApplication::Render()
  326. {
  327.     // Clear the backbuffer
  328.     m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
  329.                          0x00000000, 1.0f, 0L );
  330.  
  331.     // Begin the scene 
  332.     if( FAILED( m_pd3dDevice->BeginScene() ) )
  333.         return S_OK;
  334.  
  335.     // Stage 0 is the base texture, with the height map in the alpha channel
  336.     m_pd3dDevice->SetTexture( 0, m_pEmbossTexture );
  337.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  338.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  339.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  340.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  341.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1 );
  342.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  343.     
  344.     if( m_bShowEmbossMethod )
  345.     {
  346.         // Stage 1 passes through the RGB channels (SELECTARG2 = CURRENT), and 
  347.         // does a signed add with the inverted alpha channel. The texture coords
  348.         // associated with Stage 1 are the shifted ones, so the result is:
  349.         //    (height - shifted_height) * tex.RGB * diffuse.RGB
  350.         m_pd3dDevice->SetTexture( 1, m_pEmbossTexture );
  351.         m_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
  352.         m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
  353.         m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  354.         m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
  355.         m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_ADDSIGNED );
  356.         m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE|D3DTA_COMPLEMENT );
  357.         m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
  358.  
  359.         // Set up the alpha blender to multiply the alpha channel (monochrome emboss)
  360.         // with the src color (lighted texture)
  361.         m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  362.         m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
  363.         m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ZERO );
  364.     }
  365.  
  366.     // Render the object
  367.     m_pObject->Render( m_pd3dDevice );
  368.     
  369.     // Restore render states
  370.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  371.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  372.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  373.  
  374.     // Draw some text
  375.     m_pFont->DrawText(   2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  376.     m_pFont->DrawText(   2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  377.     m_pFont->DrawText(   2, 40, 0xffffff00, _T("Move the light with the mouse") );
  378.     m_pFont->DrawText(   2, 60, 0xffffff00, _T("Emboss-mode:") );
  379.     m_pFont->DrawText( 130, 60, 0xffffffff, m_bShowEmbossMethod ? _T("ON") : _T("OFF") );
  380.  
  381.     // End the scene.
  382.     m_pd3dDevice->EndScene();
  383.  
  384.     return S_OK;
  385. }
  386.  
  387.  
  388.  
  389.  
  390. //-----------------------------------------------------------------------------
  391. // Name: InitDeviceObjects()
  392. // Desc: Initialize scene objects.
  393. //-----------------------------------------------------------------------------
  394. HRESULT CMyD3DApplication::InitDeviceObjects()
  395. {
  396.     // Init the font
  397.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  398.  
  399.     // Load texture map. Note that this is a special textures, which has a
  400.     // height field stored in the alpha channel
  401.     if( FAILED( D3DUtil_CreateTexture( m_pd3dDevice, _T("emboss1.tga"), 
  402.                                        &m_pEmbossTexture, D3DFMT_A8R8G8B8 ) ) )
  403.         return D3DAPPERR_MEDIANOTFOUND;
  404.  
  405.     // Load geometry
  406.     if( FAILED( m_pObject->Create( m_pd3dDevice, _T("tiger.x") ) ) )
  407.         return D3DAPPERR_MEDIANOTFOUND;
  408.  
  409.     // Set attributes for the geometry
  410.     m_pObject->SetFVF( m_pd3dDevice, D3DFVF_EMBOSSVERTEX );
  411.     m_pObject->UseMeshMaterials( FALSE );
  412.  
  413.     // Compute the object's tangents and binormals, whaich are needed for the 
  414.     // emboss-tecnhique's texture-coordinate shifting calculations
  415.     ComputeTangentsAndBinormals();
  416.  
  417.     return S_OK;
  418. }
  419.  
  420.  
  421.  
  422.  
  423. //-----------------------------------------------------------------------------
  424. // Name: RestoreDeviceObjects()
  425. // Desc: Restore device-memory objects and state after a device is created or
  426. //       resized.
  427. //-----------------------------------------------------------------------------
  428. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  429. {
  430.     // Restore device objects
  431.     m_pObject->RestoreDeviceObjects( m_pd3dDevice );
  432.     m_pFont->RestoreDeviceObjects();
  433.  
  434.     // Set up the textures
  435.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  436.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  437.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  438.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  439.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  440.     
  441.     // Set the view and projection matrices
  442.     D3DXMATRIX  matView, matProj;
  443.     D3DXVECTOR3 vFromPt   = D3DXVECTOR3( 0.0f, 0.0f, 3.5f );
  444.     D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  445.     D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  446.     D3DXMatrixLookAtLH( &matView, &vFromPt, &vLookatPt, &vUpVec );
  447.     FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  448.     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 1000.0f );
  449.     m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  450.     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  451.  
  452.     // Setup a material
  453.     D3DMATERIAL8 mtrl;
  454.     D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f );
  455.     m_pd3dDevice->SetMaterial( &mtrl );
  456.  
  457.     // Set up the light
  458.     D3DUtil_InitLight( m_Light, D3DLIGHT_POINT, 5.0f, 5.0f, -20.0f );
  459.     m_Light.Attenuation0 = 1.0f;
  460.     m_pd3dDevice->SetLight( 0, &m_Light );
  461.     m_pd3dDevice->LightEnable( 0, TRUE );
  462.     
  463.     // Set miscellaneous render states
  464.     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,  TRUE );
  465.     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
  466.     m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,  0x00444444 );
  467.  
  468.     ApplyEnvironmentMap();
  469.  
  470.     return S_OK;
  471. }
  472.  
  473.  
  474.  
  475.  
  476. //-----------------------------------------------------------------------------
  477. // Name: InvalidateDeviceObjects()
  478. // Desc: Called when the device-dependent objects are about to be lost.
  479. //-----------------------------------------------------------------------------
  480. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  481. {
  482.     m_pFont->InvalidateDeviceObjects();
  483.     m_pObject->InvalidateDeviceObjects();
  484.  
  485.     return S_OK;
  486. }
  487.  
  488.  
  489.  
  490.  
  491. //-----------------------------------------------------------------------------
  492. // Name: DeleteDeviceObjects()
  493. // Desc: Called when the app is exiting, or the device is being changed,
  494. //       this function deletes any device dependent objects.
  495. //-----------------------------------------------------------------------------
  496. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  497. {
  498.     SAFE_RELEASE( m_pEmbossTexture );
  499.  
  500.     m_pObject->Destroy();
  501.     m_pFont->DeleteDeviceObjects();
  502.  
  503.     SAFE_DELETE_ARRAY( m_pTangents );
  504.     SAFE_DELETE_ARRAY( m_pBinormals );
  505.  
  506.     return S_OK;
  507. }
  508.  
  509.  
  510.  
  511.  
  512. //-----------------------------------------------------------------------------
  513. // Name: FinalCleanup()
  514. // Desc: Called before the app exits, this function gives the app the chance
  515. //       to cleanup after itself.
  516. //-----------------------------------------------------------------------------
  517. HRESULT CMyD3DApplication::FinalCleanup()
  518. {
  519.     SAFE_DELETE( m_pFont );
  520.     SAFE_DELETE( m_pObject );
  521.  
  522.     return S_OK;
  523. }
  524.  
  525.  
  526.  
  527.  
  528. //-----------------------------------------------------------------------------
  529. // Name: ConfirmDevice()
  530. // Desc: Called during device intialization, this code checks the device
  531. //       for some minimum set of capabilities
  532. //-----------------------------------------------------------------------------
  533. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior, 
  534.                                           D3DFORMAT Format )
  535. {
  536.     if( dwBehavior & D3DCREATE_PUREDEVICE )
  537.         return E_FAIL; // GetTransform doesn't work on PUREDEVICE
  538.  
  539.     // This sample uses the ADDSIGNED texture blending mode
  540.     if( 0 == ( pCaps->TextureOpCaps & D3DTEXOPCAPS_ADDSIGNED ) )
  541.         return E_FAIL;
  542.     if( pCaps->MaxTextureBlendStages < 2 )
  543.         return E_FAIL;
  544.  
  545.     return S_OK;
  546. }
  547.  
  548.  
  549.  
  550.  
  551. //-----------------------------------------------------------------------------
  552. // Name: MsgProc()
  553. // Desc: Overrrides the main WndProc, so the sample can do custom message 
  554. //       handling (e.g. processing mouse, keyboard, or menu commands).
  555. //-----------------------------------------------------------------------------
  556. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT msg, WPARAM wParam,
  557.                                     LPARAM lParam )
  558. {
  559.     switch( msg )
  560.     {
  561.         case WM_COMMAND:
  562.             if( LOWORD(wParam) == IDM_EMBOSSTOGGLE )
  563.                 m_bShowEmbossMethod = !m_bShowEmbossMethod;
  564.             break;
  565.  
  566.         case WM_MOUSEMOVE:
  567.             if( m_pd3dDevice != NULL )
  568.             {
  569.                 FLOAT w = (FLOAT)m_d3dsdBackBuffer.Width;
  570.                 FLOAT h = (FLOAT)m_d3dsdBackBuffer.Height;
  571.                 m_Light.Position.x = 200.0f * ( 0.5f - LOWORD(lParam) / w );
  572.                 m_Light.Position.y = 200.0f * ( 0.5f - HIWORD(lParam) / h );
  573.                 m_Light.Position.z = 100.0f;
  574.                 m_pd3dDevice->SetLight( 0, &m_Light );
  575.                 ApplyEnvironmentMap();
  576.             }
  577.             break;
  578.     }
  579.  
  580.     return CD3DApplication::MsgProc( hWnd, msg, wParam, lParam );
  581. }
  582.  
  583.  
  584.  
  585.  
  586.